/**
 *  LastFM.h
 *
 *  Copyright (C) 2008  David Andrs <pda@jasnapaka.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#if !defined(AFX_LASTFM_H__63251ECB_C34F_4E43_AA44_6EDF3857B365__INCLUDED_)
#define AFX_LASTFM_H__63251ECB_C34F_4E43_AA44_6EDF3857B365__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "net/HttpConnection.h"
#include "PlaylistEntry.h"
#include "WaveDevice.h"

class CLastFM {
public:
	enum EState {
		Disconnected = 0,
		Connecting,
		Connected,
		GettingPlaylist,
		Buffering,
		Playing,
		Disconnecting,
		Error
	} State;

	CLastFM();
	virtual ~CLastFM();

	// API
	void Connect(const CString &userName, const CString &password);
	void Stop();
	void Play();
	BOOL ChangeStation(const CString &station);
	void NextTrack();
	CPlaylistEntry *GetMetaData() { return ActivePlaylistEntry; }
	DWORD GetLength() { return Length; }
	DWORD GetCurPos() { return CurPos; }
	CString GetStationName() { return StationName; }

	CString StateToString();
	CString GetCoverArtFileName() { return CoverArtFileName; }

protected:
	CString Version;
	CString ErrorMsg;

	void SetState(EState state);
	BOOL PerformHandshake();
	BOOL RequestXSPF();
	void GetCoverArt(const CString &url);

	CString UserName;
	CString Password;

	BOOL Authenticated;
	// info from the handsake
	CString Session;
	CString BaseUrl;
	CString BasePath;

	// playlist
	CString StationName;
	CList<CPlaylistEntry *, CPlaylistEntry *> Playlist;
	CPlaylistEntry *ActivePlaylistEntry;

	DWORD Length;						// num of bytes of the current track
	DWORD CurPos;						// current position
	void DestroyPlaylist();

	CHttpConnection StreamConn;

	CString CoverArtFileName;
	CString CoverArtUrl;
	CHttpConnection CoverArtConn;

	HANDLE HConnectThread;
	HANDLE HStreamThread;
	HANDLE HPlayThread;
	HANDLE HGetPlaylistThread;
	HANDLE HGetCoverArtThread;
	HANDLE HTerminate;

	static const int SLOTS;
	static const int SLOT_SIZE;
	char *Buffer;
	int ReadOffset, WriteOffset;
	HANDLE HFillSemaphore, HEmptySemaphore;
	BOOL Terminated;
	int EmptySlots;
	HANDLE HBufferFull;

	HANDLE HNextTrack;

	void ConnectProc();
	void StreamLoop();
	void StreamProc();
	void PlayProc();
	void GetPlaylistProc();
	void GetCoverArtProc();

	// Sound device
	CWaveDevice SndDev;

	friend DWORD WINAPI ConnectProcStub(LPVOID lpParam);
	friend DWORD WINAPI GetPlaylistProcStub(LPVOID lpParam);
	friend DWORD WINAPI PlayProcStub(LPVOID lpParam);
	friend DWORD WINAPI StreamProcStub(LPVOID lpParam);
	friend DWORD WINAPI GetCoverArtProcStub(LPVOID lpParam);

	friend class CMainFrame;
};

#endif // !defined(AFX_LASTFM_H__63251ECB_C34F_4E43_AA44_6EDF3857B365__INCLUDED_)
